#!/bin/bash
#
# Copyright (C) 2013 Christian Babeux <christian.babeux@efficios.com>
#
# SPDX-License-Identifier: LGPL-2.1-only

TEST_DESC="Tracefile size limits"

CURDIR=$(dirname $0)/
TESTDIR=$CURDIR/../../..

NR_ITER=1000

PAGE_SIZE=$(getconf PAGE_SIZE)

TESTAPP_PATH="$TESTDIR/utils/testapp"
TESTAPP_NAME="gen-ust-events"
TESTAPP_BIN="$TESTAPP_PATH/$TESTAPP_NAME/$TESTAPP_NAME"

NUM_TESTS=74

source $TESTDIR/utils/utils.sh

if [ ! -x "$TESTAPP_BIN" ]; then
	BAIL_OUT "No UST events binary detected."
fi

function enable_lttng_channel_size_limit ()
{
	sess_name="$1"
	channel_name="$2"
	tracefile_size_limit="$3"

	test_name="Enable channel $channel_name "
	test_name+="for session $sess_name: "
	test_name+="$tracefile_size_limit bytes tracefile limit"

	$TESTDIR/../src/bin/lttng/$LTTNG_BIN enable-channel \
	    -u $channel_name -s $sess_name --buffers-pid \
	    --subbuf-size=$PAGE_SIZE \
	    -C $tracefile_size_limit >/dev/null 2>&1

	ok $? "$test_name"
}

function enable_ust_lttng_event_per_channel ()
{
	sess_name="$1"
	event_name="$2"
	channel_name="$3"

	test_name="Enable event $event_name "
	test_name+="for session $sess_name "
	test_name+="in channel $channel_name"

	$TESTDIR/../src/bin/lttng/$LTTNG_BIN enable-event "$event_name" \
	    -s $sess_name -u -c $channel_name >/dev/null 2>&1

	ok $? "$test_name"
}

function check_file_size ()
{
	path="$1"
	file_pattern="$2"
	expected_max_size="$3"

	find $path -name "$file_pattern" -exec stat -c '%n %s' {} \; \
	    | while read file_info;
	do
		name=$(echo $file_info | cut -f1 -d ' ')
		size=$(echo $file_info | cut -f2 -d ' ')

		if [ "$size" -gt "$expected_max_size" ]; then
			diag_msg="file: $name size: $size"
			diag_msg+="expected maximum size: $expected_max_size"
			diag "$diag_msg"
			exit 1
		fi
	done

	ok $? "File size validation"
}

function test_tracefile_size_limit ()
{
	local size_limit="$1"
	local trace_path=$(mktemp -d -t "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
	local session_name=$(randstring 16 0)
	local channel_name="channel"
	local event_name="tp:tptest"

	diag "Test tracefile size limit : $size_limit bytes"

	create_lttng_session_ok $session_name $trace_path

	enable_lttng_channel_size_limit \
	    $session_name $channel_name $size_limit

	enable_ust_lttng_event_per_channel \
	    $session_name $event_name $channel_name

	start_lttng_tracing_ok $session_name

	$TESTAPP_BIN -i $NR_ITER >/dev/null 2>&1

	stop_lttng_tracing_ok $session_name

	destroy_lttng_session_ok $session_name

	# Validate file size, each one shall be no larger than the
	# specified size limit

	check_file_size $trace_path "${channel_name}_*" $size_limit

	# Validate tracing data, we should at least have some events

	validate_trace_path_ust_pid "$trace_path" "" "gen-ust-events"
	validate_trace $event_name $trace_path

	rm -rf $trace_path
}

function test_tracefile_size_limit_pagesize ()
{
	# Set a size limit lower than the page_size
	local size_limit="$(($PAGE_SIZE-2))"
	local trace_path=$(mktemp -d -t "tmp.${FUNCNAME[0]}_trace_path.XXXXXX")
	local session_name=$(randstring 16 0)
	local channel_name="channel"
	local event_name="tp:tptest"

	diag "Test tracefile size limit lower than PAGE_SIZE : $size_limit bytes"

	create_lttng_session_ok $session_name $trace_path

	enable_lttng_channel_size_limit \
	    $session_name $channel_name $size_limit

	enable_ust_lttng_event_per_channel \
	    $session_name $event_name $channel_name

	start_lttng_tracing_ok $session_name

	$TESTAPP_BIN -i $NR_ITER >/dev/null 2>&1

	stop_lttng_tracing_ok $session_name

	destroy_lttng_session_ok $session_name

	# Validate file size, expect file size to be equal to the page size

	check_file_size $trace_path "${channel_name}_*" $PAGE_SIZE

	# Validate tracing data, we should at least have some events

	validate_trace_path_ust_pid "$trace_path" "" "gen-ust-events"
	validate_trace $event_name $trace_path

	rm -rf $trace_path
}

plan_tests $NUM_TESTS

print_test_banner "$TEST_DESC"

bail_out_if_no_babeltrace

start_lttng_sessiond

# Test with multiples of PAGE_SIZE
LIMITS=("$(($PAGE_SIZE))"
	"$(($PAGE_SIZE*2))"
	"$(($PAGE_SIZE*4))"
	"$(($PAGE_SIZE*8))"
	"$(($PAGE_SIZE*16))"
	"$(($PAGE_SIZE*32))")

for limit in ${LIMITS[@]};
do
	test_tracefile_size_limit $limit
done

# Test with a value that is not a multiple of PAGE_SIZE
test_tracefile_size_limit "$(($PAGE_SIZE+1024))"

# Test that a value lower than the PAGE_SIZE is rounded to it
test_tracefile_size_limit_pagesize

stop_lttng_sessiond
